home *** CD-ROM | disk | FTP | other *** search
/ Amiga Mag HDD Backup / Amiga Mag HDD Backup.zip / Amiga Mag HDD Backup / Alexander.img.bin / Alexander.img / tech 4.1 editorial Archive.sit / Griebling / HUGE Numbers (Part 1) < prev    next >
Text File  |  1993-06-16  |  17KB  |  321 lines

  1. HUGE NUMBERS
  2.  
  3.  
  4. Introduction
  5.  
  6. This series of three articles explores an alternate floating point number
  7. system (called Extended Precision Numbers or ExNumbers) which allows an almost
  8. unlimited number of digits and can exactly represent all decimal fractions.
  9.  
  10. To demonstrate a practical use of ExNumbers, a scientific calculator is
  11. incrementally developed so that each article adds a major new capability. The
  12. final calculator has support for logical, transcendental, logarithmic, and
  13. exponential operations and is implemented as a Workbench-compatible tool, with
  14. either mouse-driven or keypad entry of complete equations.
  15.  
  16. This article introduces the ExNumbers, describes utilities such as comparison
  17. of two numbers, absolute value, digit shifting, and multiplication/division by
  18. ten, and develops the basic operations of addition, subtraction,
  19. multiplication, and division.  Next, various conversions to/from ExNumbers are
  20. covered.  Finally, there is a brief tour of the initial CLI-based calculator to
  21. demonstrate the power of ExNumbers in a real application.
  22.  
  23.  
  24. Amiga Math Problems
  25.  
  26. The Amiga has an almost embarrassing abundance of floating point math
  27. libraries which include the Fast Floating Point (FFP) library, IEEE 32-bit
  28. and IEEE 64-bit floating point libraries.  The latter two are supported by the
  29. Amiga's floating point coprocessor.  But there are serious deficiencies in all
  30. of these numerical representations.
  31.  
  32. The chief problem with these floating point formats is that they are encoded as
  33. binary numbers (mathematical base 2) while we tend more naturally to decimal
  34. numbers (base 10).  As a consequence, the fractional representations of the
  35. binary numbers are usually slightly different from the decimal number fractions
  36. that we would expect.  For example, the number 0.8 is exactly representable as
  37. a decimal number while the closest binary fraction, in IEEE 32-bit format, ends
  38. up being 0.799999952316284.  This difference is very important to business
  39. people who can't get their spreadsheets to balance when accumulated round-off
  40. errors don't balance out to zero.  ExNumbers can represent all decimal
  41. fractions exactly so no pennies are gained or lost.
  42.  
  43. A second problem is that the maximum resolution supported by the IEEE 64-bit
  44. format is only about 15 digits.  This limitation may be very serious to
  45. very large corporations whose accumulated income is numbered in billions of
  46. dollars and to space explorers who need to send a space probe to an exact
  47. orbital position.  With a virtually unlimited number of digits, ExNumbers can
  48. again meet the need for higher resolutions.
  49.  
  50. There is a down side to the use of ExNumbers.  Since they are implemented in
  51. software, they are slower than coprocessor-based floating point numbers for
  52. an equivalent number of digits.  Certainly, when using many digits, the
  53. calculations are slower.  In the proposed calculator application, however,
  54. the slower speed is not noticeable.
  55.  
  56.  
  57. Structure of ExNumbers
  58.  
  59. ExNumbers are represented as an array of 16-bit signed words, each of which
  60. contains four decimal digits and is called a Quad.  The exponent is
  61. kept in a separate 16-bit word; and the number's sign is an enumeration of
  62. `positive' and `negative' values (Figure 1).
  63.  
  64. ExNumber Quads are different from Binary-Coded Decimal (BCD) representations
  65. which are also used to store decimal-encoded numbers.  The Quads actually
  66. encode four decimal digits using a binary number so they are stored more
  67. efficiently and are faster than BCD numbers in calculations.
  68.  
  69. For example, to encode 123456.789 as an ExNumber, we first need to normalize
  70. this number to a value whose mantissa is between -10 and 10.  In other words,
  71. the number is represented in scientific notation as 1.23456789E6.  Next, this
  72. number is broken into groups of four digits, beginning at the leftmost digit.
  73. The decomposed number can now be represented as 1234 5678 9000 E0006 where the
  74. E0006 is the number's exponent.  Note the trailing zeros in the 9000 Quad.
  75. These extra digit place holders are required to pad this Quad because, if they
  76. were omitted, the final 9 would be interpreted as 0009 which would lead to the
  77. erroneous number 123456.780009.  The three Quads from this example are stored
  78. in binary form as shown in Figure 1.
  79.  
  80. <INSERT FIGURE 1 HERE>
  81.  
  82.  
  83. Utilities
  84.  
  85. Before dealing with the main mathematical operations, I need to introduce a few
  86. utilities which will be used in these algorithms.
  87.  
  88. The first of these is the ExCompare function which produces a result to
  89. indicate whether one ExNumber is equal to, greater than, or less than another
  90. ExNumber.  Although the algorithm in Listing 1 for ExCompare appears confusing,
  91. Table 1 summarizes the decisions which are used to produce an ExNumber
  92. comparison.  The notation A(+) indicates that A is positive, Aexp is an
  93. abbreviation for A's exponent, and A(i) represents the ith Quad
  94. of A.
  95.  
  96. <INSERT TABLE 1 HERE>
  97.  
  98. The ExChgSign procedure negates a number which means that the sign is toggled
  99. from positive to negative and vice versa.
  100.  
  101. ExAbs takes the absolute value of a number by forcing the sign to be positive.
  102.  
  103. ExNorm normalizes an ExNumber by removing leading zeros in a fraction and
  104. adjusting the exponent to guarantee a mantissa between -10 and 10.  For
  105. example, 0.0000456 would be normalized to 4.56E-6.
  106.  
  107. ExTimes10 increments the exponent by 1 to simulate a multiplication by 10.
  108. This procedure is much faster than really multiplying an ExNumber by 10.
  109.  
  110. Similarly, ExDiv10 subtracts 1 from the exponent to simulate a division by
  111. 10.  This procedure is also much faster than attempting to divide an ExNumber
  112. by 10.
  113.  
  114. The ExShiftRight procedure is used for shifting a single digit rightmost into
  115. an ExNumber's mantissa.  Shifting 8 into the number 6.7892 produces the number
  116. 8.67892.
  117.  
  118. ExShiftLeft shifts an ExNumber to the left by a single digit and replaces the
  119. least significant digit with a zero.
  120.  
  121. The IsZero function returns true if the ExNumber argument passed to it is equal
  122. to zero.
  123.  
  124.  
  125. Basic Arithmetic
  126.  
  127. Some of us may remember how confusing it was when first learning about binary
  128. numbers after having been exposed for most of our lives to decimal numbers.
  129. Well, the bad news is that you can forget most of what you learned about binary
  130. arithmetic; the good news is that the basic ExNumber operations of addition,
  131. subtraction, multiplication, and division are performed in very much the same
  132. way that we are used to from our daily lives.
  133.  
  134. Addition is the most basic operation in the ExNumbers module (Listing 1) and
  135. the ExAddUtility is the heart of the addition algorithm which is used by the
  136. exported ExAdd procedure.  Two positive numbers are added together in three
  137. steps: first, set the exponent of the result to the exponent of the larger
  138. number; second, shift the smaller number so that its Quads are aligned with the
  139. larger number; and finally, add together all the related Quads.  The example in
  140. Figure 2 illustrates how the numbers 1.2345678E9 and 3.21456E5 are added
  141. together.
  142.  
  143. <INSERT FIGURE 2 HERE>
  144.  
  145. The ExSubUtility subtracts two numbers using almost the same steps also used by
  146. the ExAddUtility with the exception that Quads are subtracted from each other
  147. instead of being added.
  148.  
  149. To simplify both addition and subtraction algorithms, I made a tacit assumption
  150. that both numbers would be positive.  The reason this works is seen in how the
  151. ExAdd procedure checks and manipulates the signs of the two numbers to be added
  152. together.  There are two possibilities: both numbers have the same sign (either
  153. positive or negative) so they can be added together using the ExAddUtility
  154. procedure; or the numbers have different signs so we subtract the negative
  155. number from the positive number using the ExSubUtility procedure.
  156.  
  157. The ExSub procedure is even simpler.  This algorithm makes use of the
  158. well-known property that B - C can be rewritten as B + (-C).  Thus, by negating
  159. C, a call to the ExAdd procedure produces the correct answer.
  160.  
  161. ExMult multiplies two ExNumbers together using the same techniques that we were
  162. taught in school.  Two nested loops produce a product by using the outer loop
  163. to index the first number's ith Quad and then the inner loop multiplies this
  164. Quad by each of the Quads in the second number to produce an intermediate
  165. product.  Any carries are then shifted into this intermediate product, the
  166. exponent is adjusted accordingly, and the intermediate product is added to the
  167. final result.  The above process is repeated until an intermediate product has
  168. been produced and added to the final result for each Quad in the first number.
  169. Figure 3 demonstrates the multiplication of 1.2345678E5 and 9.8765432E10.
  170.  
  171. <INSERT FIGURE 3 HERE>
  172.  
  173. The division algorithm should also be familiar to everyone.  First, the
  174. result's exponent is calculated by subtracting the divisor's exponent from the
  175. dividend's exponent.  Next, the divisor and dividend are normalized and they
  176. are forced to be positive numbers.  This step is equivalent to lining up the
  177. divisor and dividend prior to beginning a manual division.  Once again, two
  178. nested loops are used but now the outer loop iterates over all the digits in an
  179. ExNumber while the inner loop increments a quotient counter and subtracts the
  180. divisor from the dividend as long as the dividend is greater than or equal to
  181. the divisor.  This is roughly what we do when manually comparing the divisor
  182. with the dividend and estimate a quotient which when multiplied by the divisor
  183. and subtracted from the dividend leaves the dividend less than the divisor. Our
  184. algorithm here, however, replaces the multiplication/subtraction step with
  185. just a series of subtractions.  Finally, the divisor is divided by 10 to shift
  186. it within the range of the dividend for the next digit of the quotient and the
  187. whole process repeats.  The division algorithm's outer loop guarantees that
  188. enough quotient digits are produced to fill all the ExNumber Quads.  Figure 4
  189. takes you through the steps involved in dividing 3.550E2 by 1.130E2.
  190.  
  191. <INSERT FIGURE 4 HERE>
  192.  
  193.  
  194. String Conversions
  195.  
  196. Before getting on to the actual calculator project, a couple of procedures are
  197. still missing.  We need a way of translating a string into an ExNumber and,
  198. conversely, producing a string from an ExNumber.
  199.  
  200. The StrToExNum procedure accomplishes the first of our goals.  This algorithm
  201. parses a string into a set of digits (0-9), signs (+, -), and punctuation (.,
  202. E).  First, leading spaces are stripped off and the sign of the number is
  203. determined.  Then, as each digit is encountered, it is packed into a Quad at a
  204. position just to the right of the previous digit.  The ExNumber's Quads are
  205. indexed by a digit counter which is also used to let us know when enough digits
  206. have been gathered.  An exponent counter is incremented for each digit in the
  207. number. When reaching the digit maximum, only the exponent counter continues to
  208. be incremented but no more digits are added to the ExNumber. When a decimal is
  209. reached, the exponent counter increments are stopped.  If an `E' (exponent) is
  210. encountered, the ExNumber's mantissa is considered complete and the exponent's
  211. sign is determined.  All following digits are merged into the ExNumber's
  212. exponent to which the exponent counter is either added or subtracted--depending
  213. on whether the exponent is positive or negative.
  214.  
  215. The second conversion routine, ExNumToStr, produces a character string from an
  216. ExNumber.  Two different floating point number formats are supported:
  217. scientific notation (e.g., 1.23E10) and floating point notation (e.g.,
  218. 234.234).  Floating point notation is used whenever the ExNumber is small
  219. enough to be represented in a field of `MaxDigits', which represents the
  220. maximum number of digits selected by the user. Both conversions begin by
  221. checking the sign of the ExNumber and inserting a minus sign if the number is
  222. negative.
  223.  
  224. The scientific notation conversion continues by rounding the ExNumber to the
  225. number of decimal places specified by the `Decimal' argument.  The leftmost
  226. digit is then inserted into the string, followed by a decimal point.  Exactly
  227. `Decimal' digits are placed after the decimal point (even if they are all
  228. zeros).  The exponent symbol, `E', is added to the output string, followed by
  229. the exponent's sign.  A Modula-2 library function called ConvNumToStr, which
  230. converts integers into strings, is then used to convert the exponent into a
  231. string which is appended at the end of the output string.
  232.  
  233. Converting ExNumbers into floating point notation is a bit more complicated.
  234. As before, the number is rounded to maximum number of digits--in this case, the
  235. exponent size plus the number of specified decimal places.  If the ExNumber is
  236. less than zero, a leading `0.' is placed in the string, followed by enough
  237. zeros to reduce the number's exponent to zero.  Next, enough digits are placed
  238. into the output string to satisfy the requested number of decimal places or
  239. exhaust the total number of digits in an ExNumber, whichever comes first.
  240. While placing these digits in the output string, a counter (InCnt) also keeps
  241. track of the decimal point so it can be placed at the right place in the output
  242. string.  The last step of the conversion process removes trailing zeros from
  243. numbers like 35.123000000 to give more readable numbers like 35.123.
  244.  
  245.  
  246. The CLI Calculator
  247.  
  248. Listing 2 gives the complete calculator source code which supports the basic
  249. mathematical operations covered in this article.  The calculator is implemented
  250. with a very basic tokenizer (GetToken), which takes a stream of input
  251. characters and translates them into the set of tokens identified at the top of
  252. Listing 2 following the `Tokens' type.  Quite a few more tokens are identified
  253. than are being used in this first calculator version but this complete list
  254. should give a tantalizing view of the features which will be added in the next
  255. article.
  256.  
  257. The stream of tokens drive a simple recursive expression evaluator (Expression)
  258. which accepts prioritized infix notation with bracketing limited only by stack
  259. size and input string length restrictions (250 characters).  Operators are
  260. ordered as follows:
  261. Highest priority (reciprocal, squared), Medium priority (times, divide), Lowest
  262. priority (plus, minus, negate, and unary plus).  Thus, an expression like 2 + 5
  263. * 6 would give the expected result of 32, and not 42.
  264.  
  265. The calculator also supports `friendly' number entry which allows numbers to
  266. contain punctuation characters like commas, apostrophes, and underscores which
  267. can be used to separate groups of digits (e.g., 5,000 and 1'000'000.45).  This
  268. feature is especially useful with 50-digit numbers!
  269.  
  270.  
  271. A Sample Session
  272.  
  273. To use the calculator, make sure you either are in the directory which contains
  274. the calculator program or copy the calculator into a directory which is part
  275. of your regular command path.  Type `Calculator' from the CLI and you are
  276. greeted with a `CALC>' prompt.  Simply type in the following equation exactly
  277. as it appears (hold down the ALT key and press `2' to get the ▓ character and
  278. similarly to get the ¡╣ hold the ALT key and press `N', then `1'), and
  279. enter a Return:
  280.  
  281. 4 * Pi * (89.234 + 4E1 / 2.0)▓ - (2-╣ * 56.78 * 10)
  282.  
  283. The answer 149658.8731 appears on the next line after the equation.  Note the
  284. use of the name `Pi' to represent the mathematical quantity 3.141592..., the
  285. squared operator (▓), and the reciprocal operator (¡╣).  These extensions
  286. were trivial to add to the calculator and extend its usefulness.  This example
  287. also shows a variety of number formats: integer, floating point, and scientific
  288. notation.
  289.  
  290. The default settings for the calculator give floating point number results.  If
  291. you want to fix the decimal point, just type `DEC 2', for example, to set the
  292. number of decimal points to two digits.  To restore to floating point format,
  293. type `DEC 0'.  To toggle between floating point and scientific notation type
  294. `SCI'.
  295.  
  296. Experiment on your own with the calculator to see how it handles various errors
  297. like illegal characters and mismatched brackets.  If you have a Modula-2
  298. compiler, attempt some extensions to the calculator, to recognize additional
  299. mathematical constants like the base of the natural logarithm (e) or attempt a
  300. cubed (x│) operator.
  301.  
  302.  
  303. Summary
  304.  
  305. This article introduced a new floating point number system called ExNumbers
  306. which solve some problems inherent in the IEEE floating point numbers used in
  307. the Amiga.  I briefly described several utility functions which help to
  308. manipulate ExNumbers and then explained how the basic mathematical operations
  309. of addition, subtraction, multiplication, and division were implemented.  As a
  310. prelude to introducing the calculator, I showed how ExNumbers are converted
  311. into strings and conversely how strings are translated into ExNumbers.  I then
  312. described the calculator program and demonstrated several features of the
  313. CLI calculator.
  314.  
  315. In the next article I'll add an ExInteger module which gives us 172-bit logical
  316. operations (AND, OR, XOR, BIT, SHIFTs) and base conversion functions.  As well,
  317. an ExMathLib0 module will be introduced which uses the Amiga's coprocessor to
  318. give ExNumber calculations with exponential, power, trigonometric, and
  319. logarithmic functions.  All these new operators and functions will be
  320. integrated into an improved CLI calculator which should be comparable to
  321. commercial products.